use super::{
    err, err_value, json, ok, throw_err, update_side, update_stock, Base, Client, ECode, Lock,
    MapSv, Resp, TBase, VBase, VMap, Value,
};
use tracing::{instrument, warn};

pub struct Side;

impl Base for Side {}
impl TBase for Side {}

impl Side {
    pub async fn do_cmd(&self, para: &Value, cmd: &str, client: &Client, lock: Lock) -> Resp {
        let data = para.ckobj()?;
        let line = data.ck_str("line")?;

        match cmd {
            "scrap" => self.do_scrap(line, data, client, lock).await,
            _ => throw_err!(ECode::NoServe, "no side serve"),
        }
    }

    #[instrument(skip_all, name = "do_out")]
    async fn do_scrap(&self, line: &str, data: &MapSv, client: &Client, lock: Lock) -> Resp {
        let _ = lock.lock().await;

        let sn = data.ck_str("sn")?;
        let uname = data.ck_str("uname")?;
        let des = data.ck_str("des")?;
        let num = data.ck_i64("num")?;

        let mt = data.ck_str("mt")?;
        let mt_mod = self.get_mt_type(mt)?;

        let side = data.ck_str("side")?;
        let side_mod = self.get_side_type(side)?;

        update_side(line, &side_mod, sn, num, false, client).await?;

        let opt = json!({
            "tab": "lgscrap",
            "psn": sn,
            "wsn": "hand",
            "data": {
                "picknum": num,
                "uname": uname,
                "des": des,
            }
        });

        if let Err(e) = update_stock(line, &opt, sn, &mt_mod, num, client).await {
            warn!("error update stock: {:?}", e);
        }

        ok!()
    }
}
